package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
)

/*
应用程序实现步骤:

	1)解析cms发送的告警内容
	2)解析arms发送的告警内容
	3)推送告警到钉钉

cms格式其一:
	{
	  "alertName": ["cms_rds_yxpt_rc_disk"],
	  "alertRuleName": ["ae297b4_2cab74a195182fc07c"],
	  "alertState": ["ALERT"],
	  "curLevel": ["P4"],
	  "curLevelDisplay": ["Info"],
	  "curValue": ["27.5"],
	  "dimensions": [
	    {
	      "instanceId": "rm-cn9859v6m6084223s",
	      "userId": "1546884409439427"
	    }
	  ],
	  "expression": ["$Average>=20"],
	  "metricName": ["DiskUsage"],
	  "metricProject": ["acs_rds"],
	  "namespace": ["acs_rds"],
	  "ruleName": ["cms_rds_yxpt_rc_disk"],
	  "signature": ["K2vaNRxipHnqZEP1QQkHPbjURuw="],
	  "timestamp": ["1740561000000"],
	  "userId": ["1546884409439427"]
	}
*/

type cmsObject struct {
	alertName     string
	alertlevel    string
	expression    string
	metricProject string
	instanceid    string
	curValue      string
}
type Message struct {
	MsgType string `json:"msgtype"`
	Text    struct {
		Content string `json:"content"`
	} `json:"text"`
}

// 定义 content 字段的结构
type Content struct {
	AlertName    string `json:"报警名称"`
	Filter       string `json:"筛选条件"`
	AlertTime    string `json:"报警时间"`
	AlertDetails struct {
		Dimension string `json:"维度值"`
		Metrics   []struct {
			Name      string  `json:"名称"`
			TimeRange string  `json:"时间范围"`
			Type      string  `json:"类型"`
			Value     float64 `json:"值"`
			Condition string  `json:"条件"`
		} `json:"指标"`
	} `json:"报警内容"`
	Note string `json:"注意"`
}

var cmsobj cmsObject

func main() {
	http.HandleFunc("/cms/", func(resp http.ResponseWriter, req *http.Request) {
		req.ParseForm()
		//告警名称、告警级别、告警表达式、告警产品、实例id、告警当前值
		cmsobj.alertName = req.FormValue("alertName")
		cmsobj.alertlevel = strings.ToLower(req.FormValue("curLevelDisplay"))
		cmsobj.expression = req.FormValue("expression")
		cmsobj.metricProject = req.FormValue("metricProject")
		cmsobj.instanceid = req.FormValue("instanceId")
		cmsobj.curValue = req.FormValue("curValue")
		sendAlerts(cmsobj)

	})

	http.HandleFunc("/arms/", func(resp http.ResponseWriter, req *http.Request) {

		fmt.Println("===>arms")

		//reader, _ := io.ReadAll(req.Body)
		//defer req.Body.Close()

		data := `{
		"msgtype": "text",
		"text": {
			"content": "报警名称: yxpt-analysis-jvm\n筛选条件: \n报警时间: 15:35:00\n报警内容: 维度值：10.40.168.197, 最近1分钟 节点机系统负载 最大值 0.08 大于等于0 或 最近1分钟 节点机用户使用cpu_百分比 最大值 0.73 未大于等于1 或 最近1分钟 节点机空闲磁盘_byte 最小值 33008147456 大于等于1024\n\n注意：该报警未收到恢复邮件之前，正在持续报警中，24小时后会再次提醒您！"
		}
	}`

		// 解析外层 JSON
		var msg Message
		if err := json.Unmarshal([]byte(data), &msg); err != nil {
			//if err := json.Unmarshal(reader, &msg); err != nil {
			fmt.Println("解析外层 JSON 失败:", err)
			return
		}

		// 解析 content 字段
		var content Content
		lines := strings.Split(msg.Text.Content, "\n")
		for _, line := range lines {
			line = strings.TrimSpace(line)
			if strings.HasPrefix(line, "报警名称:") {
				content.AlertName = strings.TrimSpace(strings.TrimPrefix(line, "报警名称:"))
			} else if strings.HasPrefix(line, "筛选条件:") {
				content.Filter = strings.TrimSpace(strings.TrimPrefix(line, "筛选条件:"))
			} else if strings.HasPrefix(line, "报警时间:") {
				content.AlertTime = strings.TrimSpace(strings.TrimPrefix(line, "报警时间:"))
			} else if strings.HasPrefix(line, "报警内容:") {
				// 解析报警内容
				details := strings.TrimSpace(strings.TrimPrefix(line, "报警内容:"))
				parts := strings.Split(details, ",")
				content.AlertDetails.Dimension = strings.TrimSpace(strings.Split(parts[0], "：")[1])
				for _, part := range parts[1:] {
					part = strings.TrimSpace(part)
					if strings.Contains(part, "节点机系统负载") {
						metric := parseMetric(part, "节点机系统负载")
						content.AlertDetails.Metrics = append(content.AlertDetails.Metrics, metric)
					} else if strings.Contains(part, "节点机用户使用cpu_百分比") {
						metric := parseMetric(part, "节点机用户使用cpu_百分比")
						content.AlertDetails.Metrics = append(content.AlertDetails.Metrics, metric)
					} else if strings.Contains(part, "节点机空闲磁盘_byte") {
						metric := parseMetric(part, "节点机空闲磁盘_byte")
						content.AlertDetails.Metrics = append(content.AlertDetails.Metrics, metric)
					}
				}
			} else if strings.HasPrefix(line, "注意:") {
				content.Note = strings.TrimSpace(strings.TrimPrefix(line, "注意:"))
			}
		}

		// 打印解析结果
		output, err := json.MarshalIndent(content, "", "  ")
		if err != nil {
			fmt.Println("生成 JSON 失败:", err)
			return
		}
		fmt.Println(string(output))

		//
		//var data map[string]interface{}
		//if err := json.Unmarshal([]byte(tmp), &data); err != nil {
		//	fmt.Println("Failed to parse JSON")
		//}
		//
		//// 打印解析后的 map
		//fmt.Println("Parsed map:", data)

	})

	http.HandleFunc("/", func(resp http.ResponseWriter, req *http.Request) {
		req.ParseForm()
		//告警名称、告警级别、告警表达式、告警产品、实例id、告警当前值
		cmsobj.alertName = req.FormValue("alertName")
		cmsobj.alertlevel = strings.ToLower(req.FormValue("curLevelDisplay"))
		cmsobj.expression = req.FormValue("expression")
		cmsobj.metricProject = req.FormValue("metricProject")
		cmsobj.instanceid = req.FormValue("instanceId")
		cmsobj.curValue = req.FormValue("curValue")

		fmt.Println("====>/", req)

	})

	http.ListenAndServe(":12203", nil)
}

func sendAlerts(msg cmsObject) {
	fmt.Println(msg)

}

// 解析指标
func parseMetric(part, name string) struct {
	Name      string  `json:"名称"`
	TimeRange string  `json:"时间范围"`
	Type      string  `json:"类型"`
	Value     float64 `json:"值"`
	Condition string  `json:"条件"`
} {
	metric := struct {
		Name      string  `json:"名称"`
		TimeRange string  `json:"时间范围"`
		Type      string  `json:"类型"`
		Value     float64 `json:"值"`
		Condition string  `json:"条件"`
	}{
		Name: name,
	}

	// 提取时间范围
	if strings.Contains(part, "最近1分钟") {
		metric.TimeRange = "最近1分钟"
	}

	// 提取类型和值
	if strings.Contains(part, "最大值") {
		metric.Type = "最大值"
		valueStr := strings.Split(part, "最大值")[1]
		valueStr = strings.TrimSpace(strings.Split(valueStr, " ")[0])
		metric.Value = parseValue(valueStr)
	} else if strings.Contains(part, "最小值") {
		metric.Type = "最小值"
		valueStr := strings.Split(part, "最小值")[1]
		valueStr = strings.TrimSpace(strings.Split(valueStr, " ")[0])
		metric.Value = parseValue(valueStr)
	}

	// 提取条件
	if strings.Contains(part, "大于等于") {
		metric.Condition = "大于等于" + strings.Split(part, "大于等于")[1]
	} else if strings.Contains(part, "未大于等于") {
		metric.Condition = "未大于等于" + strings.Split(part, "未大于等于")[1]
	}

	return metric
}

// 解析值
func parseValue(valueStr string) float64 {
	var value float64
	_, err := fmt.Sscanf(valueStr, "%f", &value)
	if err != nil {
		fmt.Println("解析值失败:", err)
	}
	return value
}
